<?php
declare (strict_types=1);

namespace app\admin\controller;

use app\BaseController;
use app\lib\exception\BaseException;
use app\middleware\admin\Auth;
use app\model\Admins;
use app\model\ClassStudent;
use app\model\ClassTime;
use app\model\Discount;
use app\model\Invoice as InvoiceModel;
use app\model\InvoiceDetails;
use app\model\ProceedsDetails;
use app\model\Products;
use app\model\ProductsGroup;
use app\model\School;
use app\model\Ticket;
use think\Exception;
use think\facade\Db;

class Invoice extends BaseController
{
    protected $middleware = [Auth::class];

    /**
     * @param int $limit
     * @return \think\response\Json
     * @throws \think\db\exception\DbException
     */
    public function index($limit = 10)
    {
        $name = request()->param('name');
        $status = request()->param('status');
        $time = request()->param('time');
//        $school_id = request()->param('school_id');
        $student_id = request()->param('student_id');
        $type = request()->param('type');
        $data = InvoiceModel::with(['details' => function ($q) {
            $q->with(['class' => function ($q) {
                $q->where('type', 1)->with(['time']);
            }]);
        }])
            ->alias('i')
            ->join('student s', 'i.student_id = s.id', 'left')
            ->join('school sc', 'i.school_id=sc.id', 'left')
            ->join('admins a', 'a.id=i.admin_id', 'left')
//            ->where('i.school_id', $school_id)
            ->when($student_id, function ($query) use ($student_id, $type) {
                $query->where('i.student_id', $student_id);
                $res = \app\model\Proceeds::where('student_id', $student_id)
                    ->select();
                $id = array_column($res->toArray(), 'invoice_id');
                if ($id && empty($type)) {
                    $query->whereNotIn('i.id', $id);
                }
            })
            ->when($type, function ($query) use ($type, $student_id) {
                if ($type == 2) {

                } else {
                    $res = \app\model\Proceeds::where('student_id', $student_id)
                        ->select();
                    $id = array_column($res->toArray(), 'invoice_id');
                    $query->whereIn('i.id', $id);
                }

            })
            ->when($name, function ($query) use ($name) {
                $query->where('i.number', 'like', "%$name%")
                    ->whereOr('s.name', 'like', "%$name%")->field('i.*,s.name student_name,s.number student_number ,sc.name school_name,a.username');
            })->field('i.*,s.name student_name,s.number student_number ,sc.name school_name,a.username')
            ->when($status, function ($query) use ($status) {
                $query->where('i.status', $status);
            })->when($time, function ($query) use ($time) {
                $query->whereBetween('i.create_time', $time);
            })->order('i.id', 'desc')->paginate($limit)->toArray();


        foreach ($data['data'] as &$value) {

            $money = \app\model\Proceeds::where('invoice_id', $value['id'])->value('money');


            if (!empty($money)) {
                $value['debt'] = $value['price'] - $money;
            } else {
                $value['debt'] = $value['price'];
            }
            foreach ($value['details'] as &$item) {
                $item['discount']=Discount::where('id',$item['discount_id'])->value('discount');
                if ($item['type'] == 1) {
                    $value['product'][] = $item;
                } elseif ($item['type'] == 2) {
                    $value['products_group'][] = $item;
                } elseif ($item['type'] == 3) {
                    $value['course'][] = $item;
                } elseif ($item['type'] == 4) {
                    $value['ticket'][] = $item;
                }

            }

            unset($value['details']);

            // 判断是否为空，如果为空则赋值一个空数组
            if (empty($value['product'])) {
                $value['product'] = [];
            }
            if (empty($value['products_group'])) {
                $value['products_group'] = [];
            }
            if (empty($value['course'])) {
                $value['course'] = [];
            } else {
                foreach ($value['course'] as &$courseItem) {
                    foreach ($courseItem['class'] as &$v) {
                        $v['room'] = \app\model\Classroom::where('id', $v['classroom_id'])->value('name');
                        $v['name'] = Admins::where('id', $v['admin_id'])->value('username');
                    }
                    // Add more additional fields if needed
                }
            }
            if (empty($value['ticket'])) {
                $value['ticket'] = [];
            }else{
                foreach($value['ticket'] as &$i){
                    $ticketInfo = Ticket::where('id', $i['cid'])->value('ticket_item');

                    // 使用三元运算符来进行条件判断，确保避免空值和 JSON 解析错误
                    $i['ticket_item'] = isset($ticketInfo)
                        ? (json_decode($ticketInfo, true) ?: [])
                        : [];
//                    $i['ticket_item']=json_decode(Ticket::where('id',$i['cid'])->value('ticket_item'),true);
                }
            }
        }

        return $this->success($data);
    }

    public function create()
    {

        $params = request()->param();
        Db::startTrans();

        try {
            $invoice = InvoiceModel::create([
                'school_id' => $params['school_id'],
                'student_id' => $params['student_id'],
                'admin_id' => request()->userid,
                'number' => getNumber('發票'),
                'remark' => $params['remark'],
                'notice' => $params['notice'],
                'price' => $params['price']
            ]);


            foreach ($params['data'] as $item) {

                $invoicedetails = InvoiceDetails::create([
                    'invoice_id' => $invoice->id,
                    'name' => $item['name'],
                    'cid' => $item['id'],
                    'num' => $item['num'],
                    'price' => $item['price'],
                    'type' => $item['type'],
                    'total_prices' => $item['total_prices'],
                    'discount_id' => $item['discount_id'] ?? 0,
                    'discount_price' => $item['discount_price'] ?? 0,
                    'day'=>$item['deadline'] ?? 1,
                ]);

                if ($item['type'] == 1) {
                    $safety=  Products::where('id',$item['id'])->value('safety');
                    $product = \app\model\Warehouse::where('product_id', $item['id'])->where('school_id', $params['school_id'])->find();

                    if ($product) {
                        if($product->num <= $safety){
                            throw new Exception("倉庫内無" . $item['name'] . '產品庫存不足！');
                        }
                        \app\model\Warehouse::where('product_id', $product->product_id)->where('school_id',$params['school_id'])->dec('num', intval($item['num']))->update();
                        \app\model\Warehouse::where('product_id', $product->product_id)->where('school_id',$params['school_id'])->dec('points_num', intval($item['num']))->update();
                    } else {

                        Db::rollback();
                        throw new Exception("倉庫内無" . $item['name'] . '產品信息，請在本院貨倉中添加產品信息再操作');
                    }
                } elseif ($item['type'] == 2) {

                    $productGroup = ProductsGroup::where('id', $item['id'])->find();
                    if (!$productGroup) {
                        Db::rollback();
                        throw new Exception("倉庫内無產品組合內" . $item['name'] . '產品信息，請在本院貨倉中添加產品信息再操作');
                    }

                    foreach ($productGroup->product_item as $v) {

                        $productGroupResult = \app\model\Warehouse::where('product_id', $v->id)->where('school_id', $params['school_id'])->find();
                        if ($productGroupResult) {
                            \app\model\Warehouse::where('product_id', $v->id)->where('school_id',$params['school_id'])->dec('num', intval($item['num']))->update();
                            \app\model\Warehouse::where('product_id', $v->id)->where('school_id',$params['school_id'])->dec('points_num', intval($item['num']))->update();
                        } else {
                            Db::rollback();
                            throw new Exception("倉庫内無產品組合內" . $item['name'] . '產品信息，請在本院貨倉中添加產品信息再操作');
                        }
                    }

                } elseif ($item['type'] == 3 && !empty($item['course'])) {

                    foreach ($item['course'] as $v) {

                        $class = ClassTime::alias('ct')
                            ->join('class_student cs', 'cs.classtime_id=ct.id')
                            ->join('classroom cr', 'cr.id=ct.classroom_id', 'left')
                            ->join('invoice_details ind', 'ind.id=cs.invoice_details_id', 'left')
                            ->join('invoice i', 'i.id=ind.invoice_id', 'left')
                            ->where('i.status',1)
                            ->where('ind.status',1)
                            ->where('ct.admin_id', $v['admin_id'])
                            ->where('ct.classroom_id', $v['classroom_id'])
//                            ->where('ct.course_id', $v['course_id'])
                            ->where('ct.start_time', $v['start_time'])
                            ->where('ct.end_time', $v['end_time'])
                            ->where('cs.type', 1)
//                            ->where('cs.state', '<>', '取消')
                            ->field('ct.*')
                            ->find();

                        if ($class) {
                            $tab = ClassStudent::where('classtime_id', $class['id'])->where('student_id', $params['student_id'])->where('type', 1)->find();
                            if ($tab) { //需要判断是否已加入
                                $name = \app\model\Course::where('id', $item['id'])->value('name');
                                Db::rollback();
                                throw new Exception("該學生已經加入該時間段的課程，請勿重複操作");
                            }
                            ClassStudent::create([
                                'classtime_id' => $class['id'],
                                'student_id' => $params['student_id'],
                                'invoice_details_id' => $invoicedetails->id,
                                'state'=>'未點名'
                            ]);
                        } else {
//                    $startTime = substr($value['date'], 0, 10) . ' ' . substr($value['time'], 0, 5) . ':00';
//                    $endTime = substr($value['date'], 0, 10) . ' ' . substr($value['time'], 6, 5) . ':00';
                            $tab = $this->repeatedVerification($v['admin_id'], $v['classroom_id'], $v['start_time'], $v['end_time'], null, $params['school_id']);
                            if ($tab) {
                                $name = School::where('id', $params['school_id'])->value('name');
                                throw new Exception('在' . $name . '分校内的' . $v['start_time'] . '到' . $v['end_time'] . '時間段內選擇的老師或教室已被佔用，請重新規劃時間');
                            }
                            $classtime = ClassTime::create([
                                'admin_id' => $v['admin_id'],
                                'classroom_id' => $v['classroom_id'],
                                'course_id' => $item['id'],
                                'start_time' => $v['start_time'],
                                'end_time' => $v['end_time'],
                                'date' => $v['date'],
                                'time1' => $v['time1'],
                            ]);

                            ClassStudent::create([
                                'classtime_id' => $classtime->id,
                                'student_id' => $params['student_id'],
                                'invoice_details_id' => $invoicedetails->id,
                                'state'=>'未點名'
                            ]);

                        }
                    }

                } else {

                }

            }
            Db::commit();
            return $this->success();


        } catch (\Exception $e) {
            throw new BaseException(['msg' => $e->getMessage()]);
        }

    }


    public function verificationClass()
    {
        $params = request()->param();

        foreach ($params['data'] as $item) {
            if ($item['type'] == 1) {

                $class = ClassTime::alias('ct')
                    ->join('class_student cs', 'cs.classtime_id=ct.id')
                    ->join('classroom cr', 'cr.id=ct.classroom_id', 'left')
                    ->join('invoice_details ind', 'ind.id=cs.invoice_details_id', 'left')
                    ->join('invoice i', 'i.id=ind.invoice_id', 'left')
                    ->where('i.status', 1)->where('ind.status', 1)
                    ->where('ct.admin_id', $item['admin_id'])
                    ->where('ct.classroom_id', $item['classroom_id'])
                    ->where('ct.course_id', $item['course_id'])
                    ->where('ct.start_time', $item['start_time'])
                    ->where('ct.end_time', $item['end_time'])
                    ->where('cs.type', 1)
                    ->where('cr.school_id', $params['school_id'])
                    ->where('cs.state', '<>', '取消')
                    ->field('ct.*')
                    ->find();
//                    ->toArray();

                if ($class) {
                    $tab = ClassStudent::where('classtime_id', $class['id'])->where('student_id', $params['student_id'])->where('type', 1)->find();
                    if ($tab) { //需要判断是否已加入
                        $name = \app\model\Course::where('id', $item['course_id'])->value('name');
                        throw new BaseException(['msg' => "該學生已經加入該時間段的課程，請勿重複操作"]);
                    }
                } else {

                    //判断报名老师或教室是否被占用
                    $tab = $this->repeatedVerification($item['admin_id'], $item['classroom_id'], $item['start_time'], $item['end_time'], null, $params['school_id']);

                    if ($tab) {
                        $name = School::where('id', $params['school_id'])->value('name');
                        throw new BaseException(['msg' => '在' . $name . '分校内的' . $item['start_time'] . '到' . $item['end_time'] . '時間段內選擇的老師或教室已被佔用，請重新規劃時間']);
                    }
                }
            }
        }
        return $this->success();
    }

    /**
     *
     * @param int $admin_id
     * @param int $classroom_id
     * @param string $startTime
     * @param string $endTime
     * @param null $id
     * @param null $school_id
     * @return bool
     */
    protected function repeatedVerification($admin_id, $classroom_id, $startTime, $endTime, $id = null, $school_id = null)
    {


        $start = ClassTime::alias('ct')
            ->join('class_student cs', 'cs.classtime_id = ct.id')
            ->join('invoice_details ind', 'ind.id = cs.invoice_details_id', 'left')
            ->join('invoice i', 'i.id = ind.invoice_id', 'left')
            ->join('student s', 'i.student_id = s.id', 'left')
            ->where('i.status', 1)
            ->where('ind.status', 1)
            ->where(function ($q) use ($id, $school_id) {
                if ($id != null) {
                    $q->where('ct.id', '<>', $id);
                }
                if ($school_id != null) {
                    $q->where('i.school_id', $school_id);
                }
            })
            ->where('ct.start_time',$startTime)
            ->where('ct.end_time',$endTime)
//            ->where('ct.start_time', '<>', $endTime)
//            ->where(function ($q) use ($startTime, $endTime) {
//                $q->whereBetween('ct.start_time', [$startTime, $endTime])
//                    ->whereOr(function ($q) use ($startTime) {
//                        $q->where('ct.start_time', '<', $startTime)->where('ct.end_time', '>', $startTime);
//                    });
//            })
//            ->where(function ($q) use ($admin_id, $classroom_id) {
//                $q->where('ct.admin_id', $admin_id)->whereOr('ct.classroom_id', $classroom_id);
//            })
            ->count();

           if($start){
            return true;
           }
            return false;
//        $end = ClassTime::alias('ct')
//            ->join('class_student cs', 'cs.classtime_id = ct.id')
//            ->join('invoice_details ind', 'ind.id = cs.invoice_details_id', 'left')
//            ->join('invoice i', 'i.id = ind.invoice_id', 'left')
//            ->join('student s', 'i.student_id = s.id', 'left')
//            ->where('i.status', 1)
//            ->where('ind.status', 1)
//            ->where(function ($q) use ($id, $school_id) {
//                if ($id != null) {
//                    $q->where('ct.id', '<>', $id);
//                }
//                if ($school_id != null) {
//                    $q->where('i.school_id', $school_id);
//                }
//            })
//            ->where('ct.end_time', '<>', $startTime)
//            ->where(function ($q) use ($startTime, $endTime) {
//                $q->whereBetween('ct.end_time', [$startTime, $endTime])
//                    ->whereOr(function ($q) use ($endTime) {
//                        $q->where('ct.start_time', '<', $endTime)->where('ct.end_time', '>', $endTime);
//                    });
//            })
//            ->where(function ($q) use ($admin_id, $classroom_id) {
//                $q->where('ct.admin_id', $admin_id)->whereOr('ct.classroom_id', $classroom_id);
//            })
//            ->count();
//
//        if ($start != 0 || $end != 0) {
//            return true;
//        } else {
//            return false;
//        }
    }


    public function update($id)
    {
        $params = request()->param();

        InvoiceModel::where('id', $id)->update([
            'school_id' => $params['school_id'],
            'student_id' => $params['student_id'],
            'admin_id' => request()->userid,
            'remark' => $params['remark'] ?? '',
            'notice' => $params['notice'] ?? '',
            'price' => $params['price']
        ]);

        // 獲取所有相關的 InvoiceDetails 的 ID
        $invoiceDetailIds = InvoiceDetails::where('invoice_id', $id)->column('id');

        // 刪除所有相關的 ClassStudent 記錄
        if (!empty($invoiceDetailIds)) {
            ClassStudent::whereIn('invoice_details_id', $invoiceDetailIds)->delete();
        }

        // 獲取所有相關的 ClassTime 的 ID
        if (!empty($invoiceDetailIds)) {
            $classTimeIds = ClassStudent::whereIn('invoice_details_id', $invoiceDetailIds)->column('classtime_id');
            // 刪除所有相關的 ClassTime 記錄
            ClassTime::whereIn('id', $classTimeIds)->delete();
        }

        InvoiceDetails::where('invoice_id', 'in', $id)->delete();

        foreach ($params['data'] as $item) {

            $invoicedetails = InvoiceDetails::create([
                'invoice_id' => $id,
                'name' => $item['name'],
                'cid' => $item['id'],
                'num' => $item['num'],
                'price' => $item['price'],
                'type' => $item['type'],
                'total_prices' => $item['total_prices'],
                'discount_id' => $item['discount_id'],
                'discount_price' => $item['discount_price'],
                'day'=>$item['deadline'] ?? 1,
            ]);

            if ($item['type'] == 1) {

                $product = \app\model\Warehouse::where('product_id', $item['id'])->where('school_id', $params['school_id'])->find();

                if ($product) {
                    \app\model\Warehouse::where('id', $product->id)->dec('num', intval($item['num']))->update();

                } else {

                    Db::rollback();
                    throw new Exception("倉庫内無" . $item['name'] . '產品信息，請在本院貨倉中添加產品信息再操作');
                }
            } elseif ($item['type'] == 2) {

                $productGroup = ProductsGroup::where('id', $item['id'])->find();
                if (!$productGroup) {
                    Db::rollback();
                    throw new Exception("倉庫内無產品組合內" . $item['name'] . '產品信息，請在本院貨倉中添加產品信息再操作');
                }

                foreach ($productGroup->product_item as $va) {

                    $productGroupResult = \app\model\Warehouse::where('product_id', $va->id)->where('school_id', $params['school_id'])->find();
                    if ($productGroupResult) {
                        \app\model\Warehouse::where('product_id', $va['id'])->dec('num', intval($item['num']))->update();
                    } else {
                        Db::rollback();
                        throw new Exception("倉庫内無產品組合內" . $item['name'] . '產品信息，請在本院貨倉中添加產品信息再操作');
                    }
                }

            } elseif ($item['type'] == 3 && !empty($item['course'])) {

                foreach ($item['course'] as $v) {

                    if ($v['type'] == -1) {
                        ClassStudent::where('id', $v['id'])->update(['type' => -1]);
                    } else {
                        $class = ClassTime::alias('ct')
                            ->join('class_student cs', 'cs.classtime_id=ct.id', 'left')
                            ->join('classroom cr', 'cr.id=cs.invoice_details_id', 'left')
                            ->join('invoice_details ind', 'ind.id=ct.classroom_id', 'left')
                            ->join('invoice i', 'i.id=ind.invoice_id', 'left')
                            ->where('i.status', 1)->where('ind.status', 1)
                            ->where('ct.admin_id', $v['admin_id'])
                            ->where('ct.classroom_id', $v['classroom_id'])
                            ->where('ct.start_time', $v['start_time'])
                            ->where('ct.end_time', $v['end_time'])
                            ->where('cs.type', 1)
                            ->find();
                        if ($class) {

                            $tab = ClassStudent::where('classtime_id', $class['id'])->where('student_id', $params['student_id'])->where('type', 1)->find();
                            if ($tab) { //需要判断是否已加入
                                $name = \app\model\Course::where('id', $item['id'])->value('name');
                                Db::rollback();
                                throw new Exception("該學生已加入");
                            }
                            ClassStudent::create([
                                'classtime_id' => $class['id'],
                                'student_id' => $params['student_id'],
                                'invoice_details_id' => $invoicedetails->id,
                            ]);
                        } else {

                            $classtime = ClassTime::create([
                                'admin_id' => $v['admin_id'],
                                'classroom_id' => $v['classroom_id'],
                                'course_id' => $item['id'],
                                'start_time' => $v['start_time'],
                                'end_time' => $v['end_time'],
                                'date' => $v['date'],
                                'time1' => $v['time1'],
                            ]);

                            ClassStudent::create([
                                'classtime_id' => $classtime->id,
                                'student_id' => $params['student_id'],
                                'invoice_details_id' => $invoicedetails->id,
                                'state'=>'末點名'
                            ]);

                        }
                    }
                }
            }


        }


        return $this->success();

    }

    public function delete($id)
    {

        InvoiceModel::where('id', 'in', $id)->delete();
        InvoiceDetails::where('invoice_id', 'in', $id)->delete();
        return $this->success();
    }

    /**
     * 发票导出
     * @param $limit
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function derive($limit = 15)
    {
        $time = request()->param('time');
        $school_id = request()->param('school_id');
        $status = request()->param('status');
        $student_id = request()->param('student_id');
        $admin_id = request()->param('admin_id');

        $data = InvoiceDetails::alias('invd')
            ->join('invoice inv', 'invd.invoice_id=inv.id', 'left')
            ->join('student stu', 'inv.student_id=stu.id', 'left')
            ->join('proceeds_details pd', 'invd.id=pd.invoice_details_id', 'left')
            ->join('refund rf', 'rf.invoice_id=inv.id', 'left')
            ->join('school sh', 'sh.id=inv.school_id', 'left')
            ->field('invd.*,sh.name school_name,inv.number,inv.admin_id,inv.student_id,inv.status,stu.number student_number,stu.name student_name,rf.refund,pd.grandtotal')
            ->when($time, function ($query) use ($time) {
                $query->whereBetween('invd.create_time', $time);
            })->when($school_id, function ($query) use ($school_id) {
                $query->where('inv.school_id', $school_id);
            })
            ->when($status, function ($query) use ($status) {
                $query->where('inv.status', $status);
            })
            ->when($student_id, function ($query) use ($student_id) {
                $query->where('inv.student_id', $student_id);
            })
            ->when($admin_id, function ($query) use ($admin_id) {
                $query->where('inv.admin_id', $admin_id);
            })->paginate($limit);

        $num = [];
        $ids = [];

        foreach ($data as &$item) {
            $pro = \app\model\Proceeds::where('invoice_id', $item['id'])->find();
            $refund = \app\model\Refund::where('invoice_id', $item['id'])->find();
            $item['total'] += $item['total_prices'];
            $num[] = $item['total_prices'];
            $ids[] = $item['id'];
            $item['money'] = $pro['money'];
            $item['debt'] = $pro['debt'];
            $item['refund'] = $refund['refund'] ?: 0;
        }
        unset($item);
        $num = array_sum($num);
        return $this->success(compact('data', 'num'));
    }

    public function derivepro($limit = 15)
    {
        $time = request()->param('time');
        $school_id = request()->param('school_id');
        $status = request()->param('status');
        $student_id = request()->param('student_id');
        $admin_id = request()->param('admin_id');
        $cid = request()->param('cid');
//        ->join('school sc', 'i.school_id=sc.id', 'left')
        $data = InvoiceDetails::alias('invd')
            ->join('invoice inv', 'invd.invoice_id=inv.id', 'left')
            ->join('student stu', 'inv.student_id=stu.id', 'left')
            ->join('proceeds_details pd', 'invd.id=pd.invoice_details_id', 'left')
            ->join('refund rf', 'rf.invoice_id=inv.id', 'left')
            ->join('school sh', 'sh.id=inv.school_id', 'left')
            ->field('invd.*,sh.name school_name,inv.number,inv.admin_id,inv.student_id,inv.status,stu.number student_number,stu.name student_name,rf.refund,pd.grandtotal')
            ->when($time, function ($query) use ($time) {
                $query->whereBetween('invd.create_time', $time);
            })->when($school_id, function ($query) use ($school_id) {
                $query->where('inv.school_id', $school_id);
            })
            ->when($status, function ($query) use ($status) {
                $query->where('inv.status', $status);
            })
            ->when($student_id, function ($query) use ($student_id) {
                $query->where('inv.student_id', $student_id);
            })
            ->when($admin_id, function ($query) use ($admin_id) {
                $query->where('inv.admin_id', $admin_id);
            })
            ->when($cid, function ($query) use ($cid) {
                $query->whereIn('invd.cid', $cid);
            })
            ->paginate($limit);
        return $this->success($data);
    }
}
